import { h, fragment, JSXProps, JSXComponent } from '@knno/dom/jsx';
import { InlineEditor, EditCommand, ToolbarData, TOOLBAR_CHANGE } from './inlineEditor';
import { richEditorStyle } from './rich/richEditor.css';
import { Mutable } from './mutable';
import { EventBus, isDescendant } from '../tools/utils';
import { Button, UIButton } from './button';
import SVGTable from '@mdi/svg/svg/table.svg';
import SVGImg from '@mdi/svg/svg/image-outline.svg';
import SVGAlignCenter from '@mdi/svg/svg/format-align-center.svg';
import SVGAlignLeft from '@mdi/svg/svg/format-align-left.svg';
import SVGAlignRight from '@mdi/svg/svg/format-align-right.svg';
import SVGBold from '@mdi/svg/svg/format-bold.svg';
import SVGItalic from '@mdi/svg/svg/format-italic.svg';
import SVGUnderline from '@mdi/svg/svg/format-underline.svg';
import SVGTextSize from '@mdi/svg/svg/format-size.svg';
import SVGTextColor from '@mdi/svg/svg/format-color-text.svg';
import SVGFillColor from '@mdi/svg/svg/format-color-fill.svg';
import { DICT } from '../dict';
import { popupMenu } from '../tools/ui';
import { ColorPicker } from '../components/colorPicker/colorPicker';
import { getLanguage } from '@knno/i18n';

export interface RichEditorProps extends JSXProps<RichEditor> {
	source?: string;
}

function isBold(str: string): boolean {
	if (str === 'bold') return true;
	if (/^\d+$/.test(str)) {
		return parseInt(str) > 400;
	} else {
		return false;
	}
}

function isAlignLeft(str: string): boolean {
	return !/^(center|right)$/i.test(str);
}

function isAlignCenter(str: string): boolean {
	return str === 'center';
}

function isAlignRight(str: string): boolean {
	return str === 'right';
}

export class RichEditor extends JSXComponent<RichEditor> {
	private eventBus: EventBus<EditCommand> = new EventBus<EditCommand>();

	constructor(attrs: RichEditorProps) {
		const eventBus = new EventBus<EditCommand>();
		eventBus.subscribe(TOOLBAR_CHANGE, (evt, data) => {
			toolbar?.refresh(data);
		});
		let toolbar: Mutable;
		let editor: InlineEditor;

		const listenSelectionChange = () => {
			const selection = window.getSelection();
			if (!selection || selection.rangeCount < 1) return;
			const range = selection.getRangeAt(0);
			if (editor && isDescendant(editor, range.startContainer)) {
				if (editor.onSelectionChange()) {
					return;
				}
			}
			this.eventBus.publish(TOOLBAR_CHANGE, undefined);
		};
		super(
			<div class={richEditorStyle}>
				<Mutable
					class="toolbar"
					ref={(t) => {
						toolbar = t;
					}}
					onmousedown={(evt) => evt.preventDefault()}
					render={(data?: ToolbarData) => {
						const elems = data?.activeElements ?? [];
						// const isTd = elems.length > 0 && elems.filter((elem) => elem.nodeName === 'TD').length == elems.length;
						const isPTd =
							elems.length > 0 &&
							elems.filter((elem) => elem.nodeName === 'P' || elem.nodeName === 'TD').length == elems.length;
						const isPTdDiv =
							elems.length > 0 &&
							elems.filter((elem) => elem.nodeName === 'P' || elem.nodeName === 'TD' || elem.nodeName === 'DIV')
								.length == elems.length;
						// const isOneTD = elems.length === 1 && elems[0].nodeName === 'TD';
						// const table = elems.length >= 1 ? findParent<HTMLTableElement>(elems[0], 'table') : null;
						// const tableInfo = table ? parseTable(table) : null;
						let btnLeft: UIButton;
						let btnCenter: UIButton;
						let btnRight: UIButton;
						return (
							<>
								<Button
									ref={(b) => (btnRight = b)}
									icon={SVGTextSize}
									menu
									title={DICT.fontSize}
									type="info-text"
									disabled={!isPTdDiv}
									onclick={function () {
										popupMenu(
											{
												menu: [
													{ value: DICT.extremelySmall, size: 0.6 },
													{ value: DICT.verySmall, size: 0.75 },
													{ value: DICT.small, size: 0.9 },
													{ value: DICT.normal, size: 1 },
													{ value: DICT.big, size: 1.4 },
													{ value: DICT.veryBig, size: 1.8 },
													{ value: DICT.extremelyBig, size: 2.2 },
												],
												refer: this,
												width: /^zh(-.+)?$/.test(getLanguage()) ? '10em' : '13em',
												pos: 'bottom-left',
											},
											(_, selectedItem) => {
												elems.forEach((elem) => {
													elem.style.fontSize = selectedItem.size + 'em';
												});
												data?.editor?.emitChange();
											}
										);
									}}
								/>
								<Button
									ref={(b) => (btnRight = b)}
									icon={SVGTextColor}
									menu
									title={DICT.textColor}
									type="info-text"
									disabled={!isPTdDiv}
									onclick={function () {
										ColorPicker.show({ refer: this, useAction: true }).onSelect((color) => {
											elems.forEach((elem) => {
												elem.style.color = color;
											});
											data?.editor?.emitChange();
										});
									}}
								/>
								<Button
									ref={(b) => (btnRight = b)}
									icon={SVGFillColor}
									menu
									title={DICT.backColor}
									type="info-text"
									disabled={!isPTdDiv}
									onclick={function () {
										ColorPicker.show({ refer: this, useAction: true }).onSelect((color) => {
											elems.forEach((elem) => {
												elem.style.backgroundColor = color;
											});
											data?.editor?.emitChange();
										});
									}}
								/>
								<span />
								<Button
									ref={(b) => (btnLeft = b)}
									title={DICT.alignLeft}
									type="info-text"
									icon={SVGAlignLeft}
									checked={isPTdDiv && isAlignLeft(window.getComputedStyle(elems[0]).textAlign)}
									disabled={!isPTdDiv}
									onclick={function () {
										this.checked(true);
										btnRight.checked(false);
										btnCenter.checked(false);
										elems.forEach((elem) => {
											elem.style.textAlign = 'unset';
											elem.style.textIndent = '';
										});
										data?.editor?.emitChange();
									}}
								/>
								<Button
									ref={(b) => (btnCenter = b)}
									title={DICT.alignCenter}
									type="info-text"
									icon={SVGAlignCenter}
									checked={isPTdDiv && isAlignCenter(window.getComputedStyle(elems[0]).textAlign)}
									disabled={!isPTdDiv}
									onclick={function () {
										this.checked(true);
										btnLeft.checked(false);
										btnRight.checked(false);
										elems.forEach((elem) => {
											elem.style.textAlign = 'center';
											elem.style.textIndent = '0';
										});
										data?.editor?.emitChange();
									}}
								/>
								<Button
									ref={(b) => (btnRight = b)}
									title={DICT.alignRight}
									type="info-text"
									icon={SVGAlignRight}
									checked={isPTdDiv && isAlignRight(window.getComputedStyle(elems[0]).textAlign)}
									disabled={!isPTdDiv}
									onclick={function () {
										this.checked(true);
										btnLeft.checked(false);
										btnCenter.checked(false);
										elems.forEach((elem) => {
											elem.style.textAlign = 'right';
											elem.style.textIndent = '0';
										});
										data?.editor?.emitChange();
									}}
								/>
								<span />
								<Button
									title={DICT.textBold}
									type="info-text"
									icon={SVGBold}
									checked={isPTd && isBold(window.getComputedStyle(elems[0]).fontWeight)}
									disabled={!isPTd}
									onclick={function () {
										this.checked(!this.checked());
										elems.forEach((elem) => {
											elem.style.fontWeight = this.checked() ? 'bold' : '';
										});
										data?.editor?.emitChange();
									}}
								/>
								<Button
									title={DICT.textItalic}
									type="info-text"
									icon={SVGItalic}
									checked={isPTd && window.getComputedStyle(elems[0]).fontStyle === 'italic'}
									disabled={!isPTd}
									onclick={function () {
										this.checked(!this.checked());
										elems.forEach((elem) => {
											elem.style.fontStyle = this.checked() ? 'italic' : '';
										});
										data?.editor?.emitChange();
									}}
								/>
								<Button
									title={DICT.textUnderline}
									type="info-text"
									icon={SVGUnderline}
									checked={isPTd && /underline/.test(window.getComputedStyle(elems[0]).textDecoration)}
									disabled={!isPTd}
									onclick={function () {
										this.checked(!this.checked());
										elems.forEach((elem) => {
											elem.style.textDecoration = this.checked() ? 'underline' : '';
										});
										data?.editor?.emitChange();
									}}
								/>
								<span />
								<Button
									type="info-text"
									icon={SVGTable}
									title={DICT.insertTable}
									disabled={elems.length !== 1 || elems[0].nodeName !== 'P'}
									onclick={() => data?.editor?.insertTable()}
								/>
								<Button
									type="info-text"
									icon={SVGImg}
									title={DICT.insertImage}
									disabled={elems.length !== 1 || elems[0].nodeName !== 'P'}
									onclick={() => data?.editor?.insertImage()}
								/>
								<div style={{ flex: 1 }}></div>
							</>
						);
					}}
				></Mutable>
				<div class="rich-text-box">
					<InlineEditor
						ref={(e) => (editor = e)}
						source={attrs?.source}
						eventBus={eventBus}
						onfocus={() => {
							this.addClass('active');
						}}
						onblur={() => {
							this.removeClass('active');
						}}
						onconnect={() => {
							document.addEventListener('selectionchange', listenSelectionChange);
						}}
						ondisconnect={() => {
							document.removeEventListener('selectionchange', listenSelectionChange);
						}}
					/>
				</div>
			</div>,
			attrs
		);
		this.eventBus = eventBus;
	}
}
